[codex] Add LG power consumption sensors - #170
Conversation
|
what unit do you have? |
|
The live unit I tested with is an LG wall-mounted A/C model Important caveat from that test: ThinQ does show energy data for this unit, but the wired-controller bus logs did not show I updated the PR accordingly:
|
There was a problem hiding this comment.
I can confirm that this code works on my units (PM07SK.NSA).
There's something to be said about the accuracy of the numbers though, which might have something to do with how to translate what is reported by the units to decimal.
Reported current power is nowhere near the jump I see in power use of my whole house when I turn one of the units on (150-200W reported while I see a jump of ~400W, for instance). The lack of accuracy is all on LG probably, but it might be good to say something about it in documentation. Actually, it looks like interpreting the data in the messages as hexadecimal integers gives the exact same numbers as I see in ThinQ, which is much closer to the power draw I see.
Also the total power consumption does not align with what I see in ThinQ. Currently it reports 00.02.EE, which translates to 35,4kWh using the method of this PR, while ThinQ reports 61.6kWh.
| ), | ||
| cv.Optional(CONF_CURRENT_POWER): sensor.sensor_schema( | ||
| unit_of_measurement=UNIT_KILOWATT, | ||
| accuracy_decimals=1, |
There was a problem hiding this comment.
The protocol reports this in 3 decimal accuracy, so better to set it to 3 decimals.
| } | ||
| } | ||
|
|
||
| static float decode_power_nibbles_(const uint8_t* buffer, size_t offset, size_t length, float divisor) { |
There was a problem hiding this comment.
Nitpick: the trailing underscore does not align with other naming conventions in this file.
| static float decode_power_nibbles_(const uint8_t* buffer, size_t offset, size_t length, float divisor) { | ||
| // Power payloads use LG's nibble format rather than binary integers. Some documented | ||
| // current-power examples contain A-F nibbles, so this intentionally is not strict BCD. | ||
| uint32_t result = 0; | ||
| for (size_t i = 0; i < length; i++) { | ||
| result = result * 100 + ((buffer[offset + i] >> 4) & 0xF) * 10 + (buffer[offset + i] & 0xF); | ||
| } | ||
| return result / divisor; | ||
| } |
There was a problem hiding this comment.
So I'm not quite sure if this is actually how these numbers should be interpreted. The current implementation leads to a power consumption sensor that rolls back every now and then on my units, whenever the trailing nibble goes from F to 0. It might also happen for the other nibbles but I haven't seen those roll over from F to 0 yet.
It surely seems like the numbers in the protocol act like normal hexidecimal numbers, i.e. 00.02.DF becomes 00.02.E0 when 1 is added. However, interpreting it as a normal hexadecimal number gives very different results from what is reported in protocol.md.
Here's the moment it rolled over from 33.5 to 33.0, which probably corresponded with 00.02.CF to 00.02.D0. Didn't catch it live in the logs yet, but I'm trying to see it happen there as well.

There was a problem hiding this comment.
The other option is that the numbers should still be interpreted this way, but the implementation of it by LG in my units is flawed.
There was a problem hiding this comment.
I just discovered that interpreting the reported current power as hexadecimal gives me the exact same numbers as ThinQ reports (in watts), so at least for current power on my units that seems to be the way. ThinQ shows at what moment it retrieved the power use, so I can align it exactly with what was logged. Example:
At the moment that ThinQ retrieved a power use of 0.55kW, my logs show this message: CF.02.00.02.29.00.04.52.00.00.00.00.07. Hex 229 translates to 553 decimal.
That still leaves the question if that's also the case for total power usage. Interpretating 00.02.EE as hex gives 750, and I have no idea how to translate that to the 61.6 kWh ThinQ reports. I'll keep tabs on different values over time to see if I can find some logic there.
There was a problem hiding this comment.
I think the encoding can now be determined with fairly high confidence. Both values appear to be normal unsigned 24-bit big-endian binary integers, rather than LG’s nibble-decimal format.
For current power:
00 02 29 = 0x0229 = 553 W, which matches ThinQ.
For accumulated energy, the counter probably has a resolution of 0.1 kWh:
00 02 EE = 0x02EE = 750 → 75.0 kWh
This also explains and fixes the observed rollback:
00 02 CF=0x02CF= 719 → 71.9 kWh00 02 D0=0x02D0= 720 → 72.0 kWh
With the current nibble-based decoder, those values incorrectly become 33.5 and 33.0 kWh.
The difference between the resulting 75.0 kWh and ThinQ’s 61.6 kWh is therefore probably not an encoding issue. It looks more like a difference in scope or reset point.
Since these are multisplit indoor units, the CC value may represent the total consumption of the complete system, while ThinQ allocates consumption to each indoor unit separately. It would be useful to check whether the ThinQ consumption of the other indoor unit or units adds up to 13.4 kWh:
61.6 + 13.4 = 75.0 kWh
Alternatively, ThinQ may show consumption since a monthly/app reset, while the wired-bus counter uses a different starting point.
There is another interesting clue in the same CF frame:
CF.02.00.02.29.00.04.52.00.00.00.00.07
00 02 29=0x0229= 553 W00 04 52=0x0452= 1106 W
1106 W is exactly twice 553 W. This may be a second system-wide power field, while the first field is allocated to the individual indoor unit, although more captures are needed to confirm that.
My suggested decoding would therefore be:
CF, bytes 2–4: unsigned 24-bit big-endian value in wattsCC, bytes 3–5: unsigned 24-bit big-endian value in 0.1 kWh
It would be useful to monitor the deltas as well. For example, 00 02 EE → 00 02 EF should mean 75.0 → 75.1 kWh, and 00 02 FF → 00 03 00 should mean 76.7 → 76.8 kWh.
There was a problem hiding this comment.
No the other unit has a total power consumption of 28.4kWh in ThinQ, so I don't think it's a total for the whole system. For that unit the message has a value of 00.01.66, which translates to 16.6kWh using the method of this PR, and 358 when interpreting it as a hex integer.
What did cross my mind was that this power consumption counter might be non-zero out of the factory because of unknown reasons, and it's just a different offset. I'm planning to collect some more values over time and see if it's a constant offset or not.
There was a problem hiding this comment.
I have checked the values again, but there is no stable offset that makes the data I get from the unit itself match ThinQ's data.
My own conclusion is that the power consumption data is wildly inaccurate, both reported by the unit and by ThinQ. One of my units was on intermittently during the night yesterday. I checked it's power consumption through four ways:
- As reported by the unit itself
- Through ThinQ
- Using an integral sensor that uses the current power reported by the unit as input
- Subtracting a normal night's power usage of my whole home from yesterday night's power usage, as the only difference was the AC being on every now and then.
The results:
- 0.3kWh (regardless of which method was used to interpret the data, it went from
00 03 30to00 03 33) - 0.0kWh
- 0.6kWh
- 0.63kWh
This shows that setting up an integral helper sensor on the current power sensor of the AC unit is very accurate, as it matches the increase in power consumption that the power meter of my house shows. I don't see any reason to use any data reported by LG, it's so far off that there's no point using it in my opinion.
Summary
Adds optional passive Home Assistant sensors for LG units that publish wired-controller power frames:
power_consumption: total energy from type0xCC/0xAC/0x2Cmessages, published in kWh.current_power: instantaneous power from type0xCF/0xAF/0x2Fmessages, published in kW.These sensors are intentionally opt-in. The bundled
base.yamlno longer exposes them by default because several units, including my live test unit, expose energy in ThinQ/WiFi but do not send the matching wired-controller frames.Fix Log
0xCand0xF.power_consumptionas kWh withtotal_increasingstate class.current_powerto kW with one decimal place, matching the examples currently documented inprotocol.md.base.yamldefaults so unsupported units do not get dead entities.0xCFexamples includeA-Fnibbles.0xCCor0xCFframes appear on the wired-controller bus.Live Test Notes
Tested against an LG wall-mounted A/C model
S3-M12JA2DAwith modem firmwareclip_hna_v1.9.229_RT.On that unit, ThinQ reports energy data, but ESPHome wired-bus logs did not show
0xCCor0xCFframes during our test window. The new sensors therefore do not update on this unit, which matches the current upstream understanding from #3: if the indoor unit never emits these frames, this controller cannot currently request them.Validation
git diff --checkuvx esphome config template.yamlusing a scratch copy with valid local placeholder values and the optional power sensors enableduvx esphome compile template.yamlusing the same scratch copy; build completed successfullyAddresses #3 for units that emit the documented wired-bus power frames.